const isObject = (target) => {
  return (
    (typeof target === 'object' || typeof target === 'function') &&
    target !== null
  );
};

const deepClone = (obj, map = new WeakMap()) => {
  if (typeof obj !== 'object' || obj === null) return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);

  if (typeof obj === 'function') return obj;
  if (map.has(obj)) return map.get(obj);
  let cloneObj = Array.isArray(obj) ? [] : {};
  map.set(obj, cloneObj);
  let symkeys = Object.getOwnPropertySymbols(obj);
  if (symkeys.length) {
    symkeys.forEach((symkey) => {
      cloneObj[symkey] = deepClone(obj[symkey], map);
    });
  }
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloneObj[key] = deepClone(obj[key], map);
    }
  }
  if (obj instanceof Set) {
    let temp = new Set();
    for (let val of obj) {
      temp.add(deepClone(val, map));
    }
    return temp;
  }
  if (obj instanceof Map) {
    let temp = new Map();
    for (let [key, val] of obj) {
      temp.set(deepClone(key, map), deepClone(val, map));
    }
    return temp;
  }
  if (obj instanceof Promise) {
    cloneObj = new Promise((resolve, reject) => {
      obj.then(
        (res) => {
          resolve(deepClone(res, map));
        },
        (err) => {
          reject(err);
        },
      );
    });
    return cloneObj;
  }
  return cloneObj;
};
const data = { a: 1, c: 2, b: { ss: 'lll', dd: 'hhh' } };
const data1 = deepClone(data);
console.log(data1);
